package com.quan.common.filter;

import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.alibaba.fastjson.JSON;
import com.quan.common.base.bean.ResultBean;
import com.quan.common.utils.CommonUtils;
import com.quan.common.utils.JwtTokenUtils;
import com.quan.common.utils.RedisOperator;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;

/**
 * 检查Token是否存在
 * 
 * @author yhaoquan
 *
 */
public class TokenFilter implements Filter {

	private static Logger logger = LoggerFactory.getLogger(TokenFilter.class);

	@Autowired
	private RedisOperator redisOperator;

	/**
	 * JwtToken秘钥
	 */
	@Value("${jwt.secret:123456}")
	private String jwtSecret;

	/**
	 * JwtToken过去时间（秒）
	 */
	@Value("${jwt.timeout:1800}")
	private Long timeout;

	/**
	 * 不需要拦截的URI请求
	 */
	private static final String excludes = "" + 
	 "(" + 
		 "(login$)|(/login)|(weixin)|(websocket)|(sockjs-node)|" + 
		 "(druid)|(actuator)|(admin-server.quan.com)|(api.mobile.quan.com)|" + 
		 "(yhaoquan.imwork.net)|(yhaoquan-wx.wicp.net)" + 
	 ")";

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;

		logger.info("访问 URL：{} {}", request.getMethod(), request.getRequestURL().toString());

		// 不需要拦截的URI
		if (requestIsExclude(request)) {
			chain.doFilter(request, response);
			return;
		}

		// 如果是微信浏览器则不执行当前过滤器
		if (CommonUtils.inWeixinBrowse(request) || StringUtils.isNotBlank(request.getHeader("APPCLIENT"))) {
			chain.doFilter(request, response);
			return;
		}

		// 验证Token，判断用户是否登录
		if (!validToken(request)) {
			response.reset();
			response.setContentType("application/json; charset=utf-8");
			ServletOutputStream out = response.getOutputStream();

			ResultBean loginTimeOut = ResultBean.loginTimeOut();
			String message = JSON.toJSONString(loginTimeOut);

			out.write(new String(message).getBytes());

			logger.debug("Token 验证失败：状态码[{}]，错误消息：{}", loginTimeOut.getStatus(), loginTimeOut.getMsg());
			return;
		} else {
			chain.doFilter(request, response);
			return;
		}
	}

	/**
	 * 验证登录Token
	 * 
	 * @param request
	 * @return
	 */
	public boolean validToken(HttpServletRequest request) {
		String token = request.getHeader("Auth-Token");

		// Token为空
		if (null == token || "".equals(token.trim())) {
			return false;
		}

		Jws<Claims> parse = JwtTokenUtils.parse(token, jwtSecret);
		if (null != parse) {
			Claims body = parse.getBody();
			boolean hasKey = this.redisOperator.hasKey("sso:token:" + body.get("userId"));
			if (hasKey) {
				this.redisOperator.expire("sso:token:" + body.get("userId"), timeout);
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	/**
	 * 判定该URL是否需要拦截
	 * 
	 * @param request
	 * @return
	 */
	private boolean requestIsExclude(HttpServletRequest request) {
		// 没有设定excludes时，所有经过filter的请求都需要被处理
		if (null == excludes || "".equals(excludes.trim())) {
			return false;
		}

		// 获取去除context path后的请求路径
		//String contextPath = request.getContextPath();
		//String uri = request.getRequestURI();
		//uri = uri.substring(contextPath.length());
		String uri = request.getRequestURL().toString();

		Pattern p = Pattern.compile(excludes);
		Matcher m = p.matcher(uri);
		// 正则表达式匹配URI被排除，不需要拦截
		return m.find();
	}

	@Override
	public void destroy() {
	}

	public static void main(String[] args) {
		String uri1 = "http://yhaoquan.imwork.net/favicon.ico";
		String excludes = "" + "(" + "(login$)|(/login)|(weixin)|(websocket)|(sockjs-node)|" + "(druid)|(actuator)|(admin-server.quan.com)|(api.mobile.quan.com)|" + "(yhaoquan.imwork.net)" + ")";
		Pattern p = Pattern.compile(excludes);
		Matcher m = p.matcher(uri1);
		System.out.println(m.find());

	}

}
